/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

package com.huawei.housekeeper.config;

import com.huawei.housekeeper.service.AuthCheckFailHandlerService;
import com.huawei.housekeeper.service.AuthCheckService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

/**
 * springSecurity配置类
 */
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Order(2)
public class GatewayWebSecurityConfig {
    // 自定义的鉴权服务，通过鉴权的才能继续访问某个请求
    @Autowired
    private AuthCheckService authCheckService;

    // 无权限访问被拒绝时的自定义处理器。如不自己处理，默认返回403错误
    @Autowired
    private AuthCheckFailHandlerService authCheckFailHandlerService;

    // security的鉴权排除的url列表
    @Autowired
    PathExcludeConfig pathExcludeConfig;

    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {
        http.authorizeExchange()
                .pathMatchers(pathExcludeConfig.getExcludedAuthpages())
                .permitAll() // 无需进行权限过滤的请求路径
                // option 请求默认放行
                .pathMatchers(HttpMethod.OPTIONS, "/**")
                .permitAll()
                // 自定义的鉴权服务，通过鉴权的才能继续访问某个请求
                .and()
                .authorizeExchange()
                .pathMatchers("/**")
                .access(authCheckService)
                .anyExchange()
                .authenticated()
                .and()
                .httpBasic()
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(authCheckFailHandlerService)
                .and()
                .csrf()
                .disable();
        // 必须支持跨域
        return http.build();
    }
}